home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Suzy B Software 2
/
Suzy B Software CD-ROM 2 (1994).iso
/
extras
/
programm
/
a56
/
examples
/
chorus.a56
< prev
next >
Wrap
Text File
|
1995-04-27
|
8KB
|
237 lines
;***************************************************************
;
; Stereo chorus for the DSP56001 signal processor.
; Developed by Quinn Jensen (jensenq@qcj.icon.com).
;
; This program fragment implements a stereo "chorus" effect
; on a DSP56001 processor. Chorus adds depth and warmth to
; sound by creating the illusion that more instruments
; are involved in the sound than really are. It does this by
; mixing together a delayed version of the input with the input
; itself. This program uses the following signal flow.
;
;
; Left in ------+------- "dry" gain -----------> sum -----> Left out
; | ^
; v |
; sum --> delay ---> "wet" gain -----+
; ^ |
; | v -
; Right in -----+------- "dry" gain -----------> sum -----> Right out
;
;
; Note that the delay line output is negated before summing with the
; right input signal. This throws in 180 degrees of phase shift
; making for interesting results even with mono inputs
; (i.e. Left in == Right in).
;
; Chorus uses a delay time of between about 10 and 50ms in some commercial
; units. This program can be configured for longer delays.
; In the chorus effect, the delay time is slowly varied, adding a very
; subtle pitch shift. The depth and speed of the delay-time modulation
; are adjustable to taste. The greater the depth or speed, the greater
; the coloration of the signal.
;
; Variations in this algorithm are possible and encouraged. I came
; up with this code after studying the impulse response and characteristics
; of a commercial stereo chorus pedal and reading various articles in magazines
; and on usenet over the years. My somewhat dry TX81 synthesizer sounds pretty
; good with this and other effects I run on the 56001.
;
; A recent article with a pretty good not-too-technical overview of chorus
; and other effects: Gary Hall, "From the Top: Effects, the Essential Musical
; Spice," _Electronic Musician_, August 1991, pp. 62-68.
;
; I would enjoy seeing any improvements to the code.
;
include "tdsg.a56" ;hardware specific initialization code
;***************************************************************
;
; Data and constants
;
;***************************************************************
dot ;remember where we were in P-space
org x:$20 ;put runtime variables in on-chip X-space
; A spreadsheet was used to calculate the following numbers
; Sample rate 32.5500 kc
;
; Delay time (4-52) 28.0000 ms delay time knob
; Depth (1-10) 10.0000 depth knob (I like it deep)
; Speed (1-10) 0.0000 speed knob (I like it slow)
;
; max depth +/- 24.0000 ms
; min delay 4.0000 ms
; max delay 52.0000 ms
; 1/2 cycle period 5.0000 s
; samples per 1/2 cyc 162750.0000
; time delta/samp 0.2949 us
; offset samp/samp 0.0096
;
doff_i equ -130 ;initial delay offset (tap)
ddeltaf equ 0.0096 ;delta-delay, per sample
dspeed_i equ 162750 ;number of samples per
;half cycle of triangle wave
;delay-time modulator
;
; Delay time (ms) tap tap delay
;
; 1 32.5500 1 0.03
; 2 65.1000 2 0.06
; 4 130.2000 4 0.12
; 5 162.7500 8 0.25
; 8 260.4000 16 0.49
; 10 325.5000 32 0.98
; 20 651.0000 64 1.97
; 25 813.7500 128 3.93
; 40 1302.0000 256 7.86
; 50 1627.5000 512 15.73
; 60 1953.0000 1024 31.46
; 70 2278.5000 2048 62.92
; 80 2604.0000 4096 125.84
; 90 2929.5000 8192 251.67
; 100 3255.0000 16384 503.35
;
; The delay line is in off-chip X memory
;
delay equ $2000
dmax equ 4096 ;125 ms (probably way too long)
;
; doff and ddelta are 48-bit quantities
;
doff dc doff_i ;current delay distance
org y:doff
dc 0
org x:doff+1
ddelta dc 0 ;delta delay per sample
org y:ddelta
dc ddeltaf
org x:ddelta+1
dspeed dc dspeed_i ;samples per half cycle of triangle modulator
dtoggle dc 0 ;current sample count
delayout
dc 0 ;current delay-line output
org y:$0
org p:dot ;go back to P-space
;***************************************************************
;
; Initialization code
;
;***************************************************************
hf_init
move #delay,r1 ;delay line input
movec #dmax-1,m1 ;
move #doff_i,n1 ;distance to output
rts
;
;***************************************************************
;
; Sample-rate computations. Call chorus_compute at
; interrupt time when both left and right inputs are
; ready.
;
; fs = 32.552083 kHz
;
; x:<in_l left-channel input
; x:<in_r right-channel input
; x:<out_l left-channel output
; x:<out_r right-channel output
;
;***************************************************************
hf_comp
jsr <saveregs
;
; output and input mix
;
clr a #.4375,x1 ;clr a, get input scale
clr b #.5,y1 ;clr b, get output scaler
move x:<delayout,y0 ;get delay out
macr y0,y1,b x:<in_l,x0 ;b = .5 * delay, x0=in_l
macr x0,y1,b b,y0 ;b += .5 * in_l, y0=b
macr x0,x1,a b,x:<out_l ;a = x1 * in_l, L = b
move y0,b ;b = -y0
neg b x:<in_r,x0 ;x0 = in_r
macr x0,y1,b ;b += .5 * in_r
macr x0,x1,a b,x:<out_r ;R = b, a += x1 * in_r
;
; delay line in
;
move a,x:(r1)+
;
; delay line length modulation. A simple triangle-wave modulator
; is used. A sine-wave modulator would be much better, especially
; with deeper and/or faster settings.
;
move l:<doff,a ;a = current offset
move l:<ddelta,x ;x = current delta
add x,a
move a,l:<doff ;new offset = a + x
move a1,n1
move x1,b ;save delta for later use
;
; smoothly transition between delay-line offsets by
; interpolating the current sample with the previous or next
; one depending on whether the delay is currently getting longer or
; shorter. Otherwise, an obnoxious click results when the offset snaps
; to the next integral value. This does have a low-pass effect on the
; delayed signal path but it is not objectionable.
;
move y:<doff,a ;compute |frac(doff)|
lsr a #$800000,x0
or x0,a #.5,x1
move a1,x0
mpy -x0,x1,a
tst b a,y0 ;y0 = 0.5 * |frac(doff)|
jpl shorter ;on positive delta, the
;delay is shortening
move (r1)- ;get previous sample
move x:(r1+n1),x0
mpy y0,x0,a #.5,b ;scale
sub y0,b (r1)+ ;compute scale for cur sample
move b,y0
move x:(r1+n1),x0 ;get cur sample
mac x0,y0,a ;scale and sum
jmp endpan
shorter
move x:(r1+n1),x0 ;get cur sample
mpy y0,x0,a #.5,b ;scale
sub y0,b (r1)+ ;compute scale for next sample
move b,y0
move x:(r1+n1),x0 ;get next sample
mac x0,y0,a (r1)- ;scale and sum
endpan
move a,x:<delayout ;store resulting output
;
; update the triangle wave modulation (sinewave would be better)
;
move x:<dtoggle,a ;decrement toggle count
move #>1,x0
sub x0,a
move a,x:<dtoggle
jgt notogg ;time to toggle?
move x:<dspeed,x0 ;yes, negate delta and reset
move l:<ddelta,a
neg a x0,x:<dtoggle
move a,l:<ddelta
notogg
bypass
jsr <restregs
rts
end